/**
 * 
 */
package Media.ui.widgets.DeviceView;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;


import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;



import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.TreeItem;

import agg.UIUtils;

import Library.Device;
//import Library.filesystem.FLO;
import Media.ui.UIExtendable;
import Media.ui.UIInterface;


/**
 * @author Hardeep
 *
 */
public class EditDevice extends UIExtendable {
	private Text textDevName = null;
	private Label lblDevName = null;
	private Label lblDevIcon = null;
	private Label labelFileFolders = null;
	private List listIcons = null;
	private Canvas canvasIconDisplay = null;
	private Tree treeFiles = null;
	private Button btnAddFile = null;
	private Button btnAddFolder = null;
	private Button btnRemoveSelected = null;
	private Button btnApply = null;
	private Button btnCancel = null;
	private Button btnViewExpandAll = null;
	private Button btnViewCollapseAll = null;
	private Group viewGroup = null;
	
	private char sep = File.separatorChar;
	private String iconsPath = UIUtils.icon_path.replace('/', sep);
	private String curDir = ".";
	private String iconExt = ".png";
	
	private ConcurrentHashMap<String, Image> icons = 
		new ConcurrentHashMap<String, Image>();
	private ConcurrentHashMap<Image, Integer> icon_map = 
		new ConcurrentHashMap<Image, Integer>();
	
	/**
	 * File system.
	 */
	private ConcurrentHashMap<TreeItem, ItemProp> fs = 
		new ConcurrentHashMap<TreeItem, ItemProp>();
	
	private TreeItem root = null;
	
	private DeviceView dv;
	
	private Device dev;
	
	private String[] filterNames = new String [] {
			"MP3 Files", 
			"All Files (*.*)"
	};
	
	private String[] filterExtensions = new String [] {
			"*.mp3", 
			"*.*"
	};
	
	public EditDevice(DeviceView dv, Device dev) {
		try {
			curDir = new File (".").getCanonicalPath();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		this.dv = dv;
		
		createShell();
		
		setDevice(dev);
	}
	
	/**
	 * This method initializes shell
	 */
	public void createShell() {
		GridData gridData14 = new GridData();
		gridData14.horizontalAlignment = GridData.FILL;
		gridData14.verticalAlignment = GridData.CENTER;
		GridData gridData13 = new GridData();
		gridData13.grabExcessHorizontalSpace = false;
		gridData13.verticalAlignment = GridData.CENTER;
		gridData13.horizontalAlignment = GridData.FILL;
		GridData gridData5 = new GridData();
		gridData5.horizontalAlignment = GridData.END;
		gridData5.verticalAlignment = GridData.BEGINNING;

		GridData gridData2 = new GridData();
		gridData2.horizontalAlignment = GridData.END;
		gridData2.grabExcessHorizontalSpace = true;
		gridData2.verticalAlignment = GridData.BEGINNING;
		GridData gridData1 = new GridData();
		gridData1.grabExcessHorizontalSpace = true;
		gridData1.verticalAlignment = GridData.CENTER;
		gridData1.horizontalSpan = 4;
		gridData1.horizontalAlignment = GridData.FILL;
		GridData gridData = new GridData();
		gridData.grabExcessHorizontalSpace = true;
		gridData.verticalAlignment = GridData.CENTER;
		gridData.horizontalAlignment = GridData.END;
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 5;
		gridLayout.makeColumnsEqualWidth = true;
		
		shell = new Shell();//SWT.CLOSE | SWT.TITLE);
		shell.setText("Edit Device: <name>");
		shell.setLayout(gridLayout);
		shell.setMinimumSize(600, 600);
		shell.setSize(600, 600);
		shell.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent arg0) {closeShell();}
		});
		
		lblDevName = new Label(getShell(), SWT.NONE);
		lblDevName.setText("Device Name:");
		lblDevName.setLayoutData(gridData);
		textDevName = new Text(getShell(), SWT.BORDER);
		textDevName.setLayoutData(gridData1);
		lblDevIcon = new Label(getShell(), SWT.NONE);
		lblDevIcon.setText("Device Icon:");
		lblDevIcon.setLayoutData(gridData2);
		
		createListIcons();
		
		createCanvasIconDisplay();
		
		labelFileFolders = new Label(getShell(), SWT.NONE);
		labelFileFolders.setText("File System:");
		labelFileFolders.setLayoutData(gridData5);
		
		createTreeFiles();
		
		UIUtils.addFillerLabel(shell);
		
		createViewOptionsGroup();
		
		UIUtils.addFillerLabel(shell);
		
		createTreeSupportButtons();
		
		UIUtils.addFillerLabel(shell);
		UIUtils.addFillerLabel(shell);
		UIUtils.addFillerLabel(shell);
		
		btnApply = new Button(getShell(), SWT.NONE); // Generated
		btnApply.setText("OK");
		btnApply.setLayoutData(gridData13);
		btnApply.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent arg0) {
				widgetSelected(arg0);
			}

			public void widgetSelected(SelectionEvent arg0) {
				closeShell();
			}
		});
		shell.setDefaultButton(btnApply);
		
		btnCancel = new Button(getShell(), SWT.NONE);
		btnCancel.setText("Cancel");
		btnCancel.setLayoutData(gridData14);
		btnCancel.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent arg0) {
				widgetSelected(arg0);
			}

			public void widgetSelected(SelectionEvent arg0) {
				closeShell();
			}
		});
	}

	private void createViewOptionsGroup() {
		GridLayout viewGroupLayout = new GridLayout();
		viewGroupLayout.numColumns = 2;
		
		GridData dataViewGroup = UIUtils.createGridData(true, false, 
				GridData.FILL, GridData.END, -1, -1, -1, -1, -1, -1, -1, -1);
		
		viewGroup = new Group(shell, SWT.NONE);
		viewGroup.setText("View Options");
		viewGroup.setLayout(viewGroupLayout);
		viewGroup.setLayoutData(dataViewGroup);
		
		// add ze optionz
		GridData collapseData = UIUtils.createGridData(true, false, 
				GridData.FILL, GridData.CENTER, viewGroupLayout.numColumns, -1, -1, -1, -1, -1, -1, -1);
		
		btnViewCollapseAll = new Button(viewGroup, SWT.NONE);
		btnViewCollapseAll.setText("Collapse Folders");
		btnViewCollapseAll.setLayoutData(collapseData);
		btnViewCollapseAll.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent arg0) {
				widgetSelected(arg0);
			}
			public void widgetSelected(SelectionEvent arg0) {
				for ( TreeItem key : fs.keySet() )
					if ( fs.get(key).itemType == ItemProp.FOLDER )
						key.setExpanded(false);
				root.setExpanded(true);
			}
		});
		
		GridData expandData = UIUtils.createGridData(true, false, 
				GridData.FILL, GridData.CENTER, viewGroupLayout.numColumns, -1, -1, -1, -1, -1, -1, -1);
		
		btnViewExpandAll = new Button(viewGroup, SWT.NONE);
		btnViewExpandAll.setText("Expand Folders");
		btnViewExpandAll.setLayoutData(expandData);
		btnViewExpandAll.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent arg0) {
				widgetSelected(arg0);
			}
			public void widgetSelected(SelectionEvent arg0) {
				for ( TreeItem key : fs.keySet() )
					if ( fs.get(key).itemType == ItemProp.FOLDER )
						key.setExpanded(true);
			}
		});
	}

	private void createTreeSupportButtons() {
		GridData gridData31 = new GridData();
		gridData31.horizontalAlignment = GridData.FILL;
		gridData31.verticalAlignment = GridData.BEGINNING;
		GridData gridData21 = new GridData();
		gridData21.horizontalAlignment = GridData.FILL;
		gridData21.verticalAlignment = GridData.BEGINNING;
		GridData gridData11 = new GridData();
		gridData11.grabExcessHorizontalSpace = false;
		gridData11.verticalAlignment = GridData.BEGINNING;
		gridData11.horizontalAlignment = GridData.FILL;
		
		btnAddFile = new Button(getShell(), SWT.NONE);
		btnAddFile.setText("Add File");
		btnAddFile.setLayoutData(gridData11);
		btnAddFile.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent arg0) {
				widgetSelected(arg0);
			}

			public void widgetSelected(SelectionEvent arg0) {
				FileDialog dialog = new FileDialog (shell, SWT.OPEN);
				// TODO make the filters generated based on supported content
				dialog.setFilterNames (filterNames);
				dialog.setFilterExtensions (filterExtensions);
				String file = dialog.open();
				if ( file != null && !file.equals("") )
					addFile(file);
			}
		});
		
		btnAddFolder = new Button(getShell(), SWT.NONE);
		btnAddFolder.setText("Add Folder");
		btnAddFolder.setLayoutData(gridData21);
		btnAddFolder.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent arg0) {
				widgetSelected(arg0);
			}

			public void widgetSelected(SelectionEvent arg0) {
				DirectoryDialog dialog = new DirectoryDialog (shell);
				String file = dialog.open();
				if ( file != null && !file.equals("") )
					addFolder(file);
			}
		});
		
		UIUtils.addFillerLabel(shell);
		
		btnRemoveSelected = new Button(getShell(), SWT.NONE);
		btnRemoveSelected.setText("Remove Selected");
		btnRemoveSelected.setLayoutData(gridData31);
	}

	private void createTreeFiles() {
		GridData gridData6 = new GridData();
		gridData6.horizontalSpan = 4;
		gridData6.horizontalAlignment = GridData.FILL;
		gridData6.verticalAlignment = GridData.FILL;
		gridData6.grabExcessVerticalSpace = true;
		gridData6.verticalSpan = 3;
		gridData6.grabExcessHorizontalSpace = false;
		
		treeFiles = new Tree(getShell(), SWT.BORDER);
		treeFiles.setLinesVisible(true);
		treeFiles.setLayoutData(gridData6);
		
		// add root
		root = new TreeItem(treeFiles, SWT.NONE);
		root.setText("root");
		root.setGrayed(true);
		treeFiles.setTopItem(root);
		treeFiles.select(root);
		fs.put(root, new ItemProp(null, root, ItemProp.FOLDER));
		treeFiles.setItemCount(1);
	}
	
	private TreeItem addTreeItem(TreeItem parent, String name, int type) {
		TreeItem t = new TreeItem(parent, SWT.NONE);
		t.setText(name);
		
		ItemProp parentProps = fs.get(parent);
		ItemProp childProps = parentProps.addChild(t);
		
		childProps.treeitem = t;
		childProps.itemType = type;
		childProps.parent = parent;
		
		fs.put(t, childProps);
		
		parent.setExpanded(true);
		
		return t;
	}

	/**
	 * Add the given file to the device, under the selected item (if a folder)
	 * in the tree. If the selected item is a file, will add to the same folder
	 * as the file.
	 * @param filename
	 */
	private void addFile(String filename) {
		// TODO add real file name filter check
		if ( !filename.endsWith(".mp3") )
			return;
		
		// TODO make this work with FLO objects
//		try {
//			dev.addFile(filename);
//		} catch (SQLException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		FLO f = dev.addFile(filename);
//		
//		TreeItem sel = treeFiles.getSelection()[0];
//		
//		ItemProp selProp = fs.get(sel); 
//		if ( selProp.itemType == ItemProp.FILE )
//			sel = selProp.parent;
//		
//		if ( sel == null )
//			sel = root;
//		
//		addTreeItem(sel, f.getName(), ItemProp.FILE);
	}
	
	/**
	 * Add the specified folder to the currently selected item if it's a FOLDER,
	 * otherwise add to the same folder the item occupies. Note that this method
	 * will recurse through up to a maximum of 5 sub folders.
	 * @param folderName
	 */
	// TODO make recursion-depth based on a setting of some sort
	private void addFolder(String folderName) {
//		try {
//			dev.addFolder(folderName);
//		} catch (SQLException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
//		addFolder(f, true, 5);
	}
	
//	private void addFolder(FLO folder, boolean recurse, int depth) 
//	throws FileNotFoundException {
//		// TODO make this work with FLO objects
////		dev.addFolder(folder, recurse, depth);
////		TreeItem sel = treeFiles.getSelection()[0];
////		ItemProp selProp = fs.get(sel);
////
////		if ( selProp.itemType == ItemProp.FILE ) {
////			sel = selProp.parent;
////			treeFiles.select(sel);
////		}
////		
////		if ( sel == null )
////			sel = root;
////		
////		if ( folder.isFLODir() ) {
////			File[] files = folder.listFiles();
////			FLO f;
////			
////			// create the new Folder TreeItem, and select it
////			TreeItem t = addTreeItem(sel, 
////					Device.getFolderName(folder.getPath()), ItemProp.FOLDER);
////			treeFiles.select(t);
////			
////			// add all files/sub-folders
////			for (int i = 0; i < files.length; i++) {
////				f = (FLO) files[i];
////				if ( f.isFLODir() )
////					addFile(f.getPath());
////				else if ( depth > 0 && recurse == true )
////					addFolder(f, recurse, depth - 1);
////			}
////			
////			// Select the old root again
////			treeFiles.select(sel);
////		}
//	}
	
	/**
	 * Set the device to be edited.
	 * @param dev
	 */
	public void setDevice(Device dev) {
		this.dev = dev;
		
		shell.setText("Edit Device: " + dev.getName());
		textDevName.setText(dev.getName());
		
		// TODO get the icon list to scroll to the selected item
		String icon = dev.getProperty("icon");
		String iconName = icon.substring(0, icon.length()-4);
		int iconPos = listIcons.indexOf(iconName);
		listIcons.remove(iconPos);
		listIcons.add(iconName, 0);
		listIcons.select(0);
		
		// TODO get a list of all files already in the device and add them to the file listing...
		
	}
	
	/**
	 * Initialize listIcons
	 */
	private void createListIcons() {
		GridData gridData4 = new GridData();
		gridData4.horizontalAlignment = GridData.FILL;
		gridData4.grabExcessHorizontalSpace = true;
		gridData4.grabExcessVerticalSpace = false;
		gridData4.horizontalSpan = 3;
		gridData4.heightHint = 100;
		gridData4.verticalAlignment = GridData.FILL;
		
		listIcons = new List(getShell(), SWT.V_SCROLL | SWT.BORDER);
		listIcons.setLayoutData(gridData4);
		
		// get all the icons
		File f = new File(curDir + sep + "src" + iconsPath);
		String[] files = f.list();
		ImageData iconData;
		
		int id = 0;
		for ( String cur_icon : files ) {
			if ( cur_icon.toLowerCase().endsWith(iconExt) ) {
				// TODO check if the 'src' in path is actually necessary on release
				iconData = new ImageData(curDir + sep + "src" + iconsPath + cur_icon);
				cur_icon = cur_icon.substring(0, cur_icon.length() - 4);
				
				Image e = new Image(Display.getCurrent(),iconData);
				listIcons.add(cur_icon);
				icons.put(cur_icon, e);
				id++;
			}
		}
		
		// add selection listener
		listIcons.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent arg0) {
				widgetSelected(arg0);
			}

			public void widgetSelected(SelectionEvent arg0) {
				canvasIconDisplay.redraw();
			}			
		});
		
		listIcons.select(0);
	}

	/**
	 * This method initializes canvasIconDisplay	
	 *
	 */
	private void createCanvasIconDisplay() {
		GridData gridData3 = new GridData();
		gridData3.grabExcessHorizontalSpace = false;
		gridData3.horizontalAlignment = GridData.FILL;
		gridData3.verticalAlignment = GridData.FILL;
		gridData3.heightHint = 64;
		gridData3.widthHint = 64;
		gridData3.grabExcessVerticalSpace = false;
		
		
		canvasIconDisplay = new Canvas(getShell(), SWT.BORDER);
		canvasIconDisplay.setBackground(new Color(Display.getCurrent(), 
				255, 255, 255));
		canvasIconDisplay.setLayoutData(gridData3);
		
		canvasIconDisplay.addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				String[] sels = listIcons.getSelection();
				if ( sels.length > 0 ) {
					String sel = sels[0];
					if ( icons.containsKey(sel) ) {
						Image iconImage = icons.get(sel);
						int y = (e.height / 2) - (dv.icon_size[0] / 2);
						int x = (e.width / 2) - (dv.icon_size[1] / 2);
						e.gc.drawImage(iconImage,x,y);	
					}
				}
			}
		});
	}

}